# 导入必要的模块和库
# os模块用于与操作系统交互，如获取环境变量
import os
# asyncio模块用于支持异步编程
import asyncio
# 从langchain_mcp_adapters.client导入MultiServerMCPClient，用于连接多个MCP服务器
from langchain_mcp_adapters.client import MultiServerMCPClient
# 从langchain.agents导入create_openai_tools_agent和AgentExecutor，用于创建和执行AI代理
from langchain.agents import create_openai_tools_agent, AgentExecutor
# 从langchain_openai导入ChatOpenAI，用于与OpenAI兼容的聊天模型交互
from langchain_openai import ChatOpenAI
# 从langchain.prompts导入ChatPromptTemplate和MessagesPlaceholder，用于创建聊天提示模板
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

# 导入文件管理工具包，用于文件操作
from langchain_community.agent_toolkits.file_management.toolkit import FileManagementToolkit
# 初始化文件管理工具包，指定根目录为"./workspace"
file_management_toolkit = FileManagementToolkit(root_dir="./workspace")
# 获取文件管理工具列表
file_tools = file_management_toolkit.get_tools()

# 设置OpenAI API密钥环境变量，用于访问OpenAI兼容的模型
os.environ["OPENAI_API_KEY"] = "sk-a4c4ac5e0a9a4e8eb0ae8a8feafad695"


# 异步函数：创建MCP客户端和相关工具
async def create_mcp_client_tools():
    # 从环境变量获取高德地图API密钥
    amap_key = os.environ.get("AGENT_AMAP_API_KEY")
    # 创建MultiServerMCPClient实例，连接到高德地图MCP服务
    # 使用Server Sent Event (SSE)传输协议
    client = MultiServerMCPClient(
        {
            "amap": {
                "url": f"https://mcp.amap.com/sse?key={amap_key}",
                "transport": "sse",  # Sever Sent Event传输协议
            }
        }
    )
    # 异步获取MCP工具
    tools = await client.get_tools()
    # 返回客户端和合并后的工具列表（MCP工具 + 文件管理工具）
    return client, tools + file_tools


# 主函数：创建和执行AI代理
async def main():
    # 调用create_mcp_client_tools函数获取客户端和工具
    client, tools = await create_mcp_client_tools()
    # 打印工具类型（调试用）
    print(type(tools))
    
    # 创建ChatOpenAI实例，配置模型参数
    llm = ChatOpenAI(
        model="qwen-plus",  # 使用通义千问plus模型
        openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",  # OpenAI API基础URL
        temperature=0.3,  # 设置温度参数，控制输出的随机性，较低值使输出更确定性
        max_retries=1,  # 设置最大重试次数
    )

    # 创建聊天提示模板，定义代理的行为模式
    prompt = ChatPromptTemplate.from_messages(
        [
            # 系统消息：定义代理的角色和能力
            (
                "system",
                "你是一个智能助手，可以使用工具来回答用户的问题，非常擅长旅游规划。",
            ),
            # 用户输入占位符：用于插入用户的具体问题
            ("user", "{input}"),
            # 消息占位符：用于存放代理执行过程中的中间结果（工具调用等）
            MessagesPlaceholder(
                variable_name="agent_scratchpad"
            ),
        ]
    )

    # 使用OpenAI工具创建代理
    agent = create_openai_tools_agent(
        llm=llm,      # 传入语言模型
        tools=tools,  # 传入可用工具
        prompt=prompt,  # 传入提示模板
    )

    # 创建代理执行器，负责执行代理并管理执行过程
    agent_executor = AgentExecutor(
        agent=agent,     # 传入创建的代理
        tools=tools,     # 传入可用工具
        max_iterations=100,  # 设置最大迭代次数，防止代理无限循环
        verbose=True,    # 设置为True以输出详细的执行过程，便于调试
    )
    
    # 定义用户问题
    # 以下是一些示例问题，但只有最后一个会被实际使用
    USER_QUESTION = "请问华清远见成都中心所在的经纬度是多少"
    USER_QUESTION = "请问华清远见成都中心到北大街沃尔玛的公交路线，请输出路线"
    USER_QUESTION = """
        - 我计划在国庆节去重庆玩2天
        - 推荐5个最优景点
        - 规划住宿问题
        - 帮我制作旅行攻略，考虑出行时间和路线，以及天气状况路线规划。
        
        - 行程规划结果在高德地图app展示，并集成到h5页面中。
        - 同一天行程景区之间我想打车前往。
        - 把以上信息生成一个HTML页面：
            - 制作网页地图自定义绘制旅游路线和位置。
            - 网页使用简约美观页面风格，景区图片以卡片展示。
            - 该页面需要能够嵌入移动端
        - 在输出的时候，通过JSON格式告诉我生成的HTML文件地址
    """
    
    # 异步调用代理执行器处理用户问题
    result = await agent_executor.ainvoke({"input": USER_QUESTION})
    # 返回执行结果
    return result


# 程序入口点：当脚本直接运行时执行
if __name__ == "__main__":
    # 使用asyncio运行主函数
    response = asyncio.run(main())
    print(response.output)